package com.coursehub.user.service.impl;

import com.coursehub.shared.exception.BusinessException;
import com.coursehub.shared.exception.ResourceNotFoundException;
import com.coursehub.shared.util.StringUtils;
import com.coursehub.user.dto.UserLoginDto;
import com.coursehub.user.dto.UserRegisterDto;
import com.coursehub.user.dto.UserUpdateDto;
import com.coursehub.user.entity.User;
import com.coursehub.user.repository.UserRepository;
import com.coursehub.user.service.UserService;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;

/**
 * 用户服务实现类
 */
@Service
@RequiredArgsConstructor
@Transactional
public class UserServiceImpl implements UserService {
    
    private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);
    
    private final UserRepository userRepository;
    private final PasswordEncoder passwordEncoder;
    
    @Override
    public User registerUser(UserRegisterDto registerDto) {
        log.info("用户注册请求: {}", registerDto.getUserAccount());
        
        // 检查用户账号是否已存在
        if (userRepository.existsByUserAccount(registerDto.getUserAccount())) {
            log.warn("用户账号已存在: {}", registerDto.getUserAccount());
            throw new BusinessException("用户账号已存在");
        }
        
        // 生成用户ID
        String userId = generateUserId(registerDto.getUserAccount());
        
        // 创建用户实体
        User user = new User();
        user.setUserId(userId);
        user.setUserName(registerDto.getUserName());
        user.setUserAccount(registerDto.getUserAccount());
        user.setUserPassword(passwordEncoder.encode(registerDto.getUserPassword())); // 加密密码
        
        User savedUser = userRepository.save(user);
        log.info("用户注册成功: {}", savedUser.getUserId());
        
        return savedUser;
    }
    
    @Override
    public User login(UserLoginDto loginDto) {
        return login(loginDto.getUserAccount(), loginDto.getUserPassword());
    }
    
    @Override
    public User login(String account, String password) {
        log.info("用户登录请求: {}", account);
        
        if (StringUtils.isBlank(account) || StringUtils.isBlank(password)) {
            throw new BusinessException("账号和密码不能为空");
        }
        
        Optional<User> userOpt = userRepository.findByUserAccount(account);
        if (userOpt.isEmpty()) {
            log.warn("用户不存在: {}", account);
            throw new BusinessException("用户不存在或密码错误");
        }
        
        User user = userOpt.get();
        if (!passwordEncoder.matches(password, user.getUserPassword())) { // 使用加密密码比较
            log.warn("密码错误: {}", account);
            throw new BusinessException("用户不存在或密码错误");
        }
        
        log.info("用户登录成功: {}", user.getUserId());
        return user;
    }
    
    @Override
    public void logout() {
        // 实现登出逻辑
        // 注意：在无状态JWT架构中，服务端无法直接使token失效
        // 通常的登出策略包括：
        // 1. 客户端删除本地存储的token
        // 2. 服务端维护token黑名单（需要Redis等缓存）
        // 3. 设置较短的token过期时间
        
        log.info("用户登出 - 建议客户端删除本地token");
        
        // 这里可以添加额外的登出逻辑，比如：
        // - 记录用户登出日志
        // - 清理用户会话相关数据
        // - 发送登出通知等
        
        // 如果需要实现token黑名单功能，可以在这里添加逻辑
        // 例如：将当前token加入黑名单，设置过期时间
        // tokenBlacklistService.addToBlacklist(token, expirationTime);
    }
    
    @Override
    public User updateUser(String userId, User user, String password) {
        log.info("更新用户信息: {}", userId);
        
        User existingUser = getUserById(userId);
        
        // 验证密码
        if (!passwordEncoder.matches(password, existingUser.getUserPassword())) {
            throw new BusinessException("密码验证失败");
        }
        
        // 更新用户信息
        if (StringUtils.isNotBlank(user.getUserName())) {
            existingUser.setUserName(user.getUserName());
        }
        if (StringUtils.isNotBlank(user.getUserPassword())) {
            existingUser.setUserPassword(passwordEncoder.encode(user.getUserPassword()));
        }
        
        User updatedUser = userRepository.save(existingUser);
        log.info("用户信息更新成功: {}", userId);
        
        return updatedUser;
    }
    
    @Override
    public User updateUserInfo(String userId, UserUpdateDto updateDto) {
        log.info("更新用户信息: {}", userId);
        
        User existingUser = getUserById(userId);
        
        // 验证当前密码
        if (!passwordEncoder.matches(updateDto.getCurrentPassword(), existingUser.getUserPassword())) {
            throw new BusinessException("当前密码验证失败");
        }
        
        // 更新用户名
        if (StringUtils.isNotBlank(updateDto.getNewName())) {
            existingUser.setUserName(updateDto.getNewName());
        }
        
        // 更新密码
        if (StringUtils.isNotBlank(updateDto.getNewPassword())) {
            existingUser.setUserPassword(passwordEncoder.encode(updateDto.getNewPassword()));
        }
        
        User updatedUser = userRepository.save(existingUser);
        log.info("用户信息更新成功: {}", userId);
        
        return updatedUser;
    }
    
    @Override
    public void deleteUser(String userId) {
        log.info("删除用户: {}", userId);
        
        if (!userRepository.existsById(userId)) {
            throw new ResourceNotFoundException("用户不存在: " + userId);
        }
        
        userRepository.deleteById(userId);
        log.info("用户删除成功: {}", userId);
    }
    
    @Override
    public User getUserById(String userId) {
        return userRepository.findById(userId)
                .orElseThrow(() -> new ResourceNotFoundException("用户不存在: " + userId));
    }
    
    @Override
    public boolean checkUserPassword(String userId, String password) {
        User user = getUserById(userId);
        return passwordEncoder.matches(password, user.getUserPassword()); // 使用加密密码比较
    }
    
    @Override
    public List<User> getAllUsers() {
        return userRepository.findAll();
    }
    
    @Override
    public boolean userExists(String userId) {
        return userRepository.existsById(userId);
    }
    
    @Override
    public boolean userExistsByAccount(String userAccount) {
        return userRepository.existsByUserAccount(userAccount);
    }
    
    /**
     * 生成用户ID
     * 规则：U + user_account
     */
    private String generateUserId(String userAccount) {
        return "U" + userAccount;
    }
}